package com.pz.cloud.framework.util;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.util.*;

public class BeanUpdateUtils {
    /**
     * 执行BeanUtils.copyProperties方法，过滤掉提交过来的object中值为null的参数。
     *
     * @param source 提交过来的object
     * @param target 数据库查出来的object
     */
    public static <T> T copyNullProperties(Object source, T target) {
        BeanUtils.copyProperties(source, target, getNullProperties(source));
        return target;
    }
    /**
     * 执行BeanUtils.copyProperties方法，过滤掉提交过来的object中值为null的参数。
     *
     * @param source 提交过来的object
     * @param target 数据库查出来的object
     */
    public static <T> T copyNullProperties(Object source, T target,String... ignorePros) {
        String[] nullProperties = getNullProperties(source);
        List<String> ignoreProList = new ArrayList<>();
        for (String ignorePro : ignorePros) {
            ignoreProList.add(ignorePro);
        }
        for (String p : nullProperties) {
            ignoreProList.add(p);
        }
        BeanUtils.copyProperties(source, target, ignoreProList.toArray(new String[ignoreProList.size()]));
        return target;
    }

    /**
     * 执行BeanUtils.copyProperties方法，过滤掉提交过来的object中值为null 和空字符串参数。
     *
     * @param source 提交过来的object
     * @param target 数据库查出来的object
     */
    public static <T> T copyWithoutEmptyProperties(Object source, T target) {
        BeanUtils.copyProperties(source, target, getEmptyProperties(source));
        return target;
    }


    /**
     * @param target 目标源数据
     * @return 将目标源中为空的字段取出
     */
    private static String[] getNullProperties(Object target) {
        BeanWrapper srcBean = new BeanWrapperImpl(target);
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        Set<String> emptyName = new HashSet<>();
        for (PropertyDescriptor p : pds) {
            Object value = srcBean.getPropertyValue(p.getName());
            if (value == null) {
                emptyName.add(p.getName());
            }
        }
        String[] result = new String[emptyName.size()];
        return emptyName.toArray(result);
    }

    /**
     * @param target 目标源数据
     * @return 将目标源中为空的字段取出
     */
    private static String[] getEmptyProperties(Object target) {
        BeanWrapper srcBean = new BeanWrapperImpl(target);
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        Set<String> noEmptyName = new HashSet<>();
        for (PropertyDescriptor p : pds) {
            Object value = srcBean.getPropertyValue(p.getName());
            if (value == null) {
                noEmptyName.add(p.getName());
            }else if(value.getClass() == String.class && StringUtils.isEmpty((String)value) ){
                noEmptyName.add(p.getName());
            }
        }
        String[] result = new String[noEmptyName.size()];
        return noEmptyName.toArray(result);
    }


    /**
     * 转换Map至Bean
     *
     * @param sources     map数据源
     * @param targetClass 复制属性值至的对象对应的类
     * @param <T>         复制属性值至的对象对应的类
     * @return 复制属性后的对象
     */
    public static <T> List<T> convert(List<Map<String, Object>> sources, Class<T> targetClass) {
        ConvertUtils.register(new DateConverter(null), java.util.Date.class);
        List<T> results = new ArrayList<T>();
        try{
            if (sources != null) {
                T result = null;
                for (Map<String, Object> source : sources) {
                    result = targetClass.newInstance();
                    org.apache.commons.beanutils.BeanUtils.copyProperties(result, source);
                    results.add(result);
                }
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }

        return results;
    }

}
